#include "base_room.h"
#include "base_desk.h"
#include "base_player.h"
#include "game_base_msg.h"
#include "string.h"
using namespace std;
BaseRoom::BaseRoom(void)
{
	
}

BaseRoom::~BaseRoom(void)
{
}

void BaseRoom::addDesk( BaseDesk* desk )
{
	desk->m_room = this;
	m_vecDesks.push_back(desk);
}

void BaseRoom::generateRoomStatusMsg(BaseProtoRoomState * roomStatus)
{
	roomStatus->maxPlayerCount = -1;
	roomStatus->currentPlayerCount = m_setPlayers.size();
	roomStatus->roomId = m_roomId;
}

bool BaseRoom::assignDesk( BaseDesk* desk, int chairId, BasePlayer* player )
{
	if(player->m_room != this) {
		return false;
	}
	if(desk->m_chairPlayers[chairId]) {
		return false;
	}
	if(chairId < 0 || chairId > 3) {
		return false;
	}

	if(player->m_desk) {
		return false;
	}

	
	desk->procPlayerJoin(player, desk->m_id, chairId);
	return true;
}

void BaseRoom::procPlayerJoin(BasePlayer* player) {
	if (m_setPlayers.find(player) != m_setPlayers.end()) {
		return;
	}
	player->m_room = this;
	m_setPlayers.insert(player);

	this->onPlayerJoin(player);
	BaseMsgS2CJoinRoom msg;
	msg.allDeskCount = m_vecDesks.size();
	
	for (unsigned int i = 0; i < m_vecDesks.size(); i++) {
		auto desk = m_vecDesks[i];

		if (!desk->hasPlayerSitted()) {
			continue;
		}

		BaseProtoDeskInfo deskInfo;
		for (int j = 0; j < 4; j++) {
			auto deskPlayer = desk->m_chairPlayers[j];

			if (!deskPlayer) {
				continue;
			}
			BaseMsgPlayerInfo playerInfo;
			deskPlayer->getPlayerInfoMsg(&playerInfo);
			deskInfo.playerNames.push_back(playerInfo);
		}
		msg.desks.push_back(deskInfo);
	
	}

	for (auto iter = m_setPlayers.begin(); iter != m_setPlayers.end(); iter++) {
		BaseMsgPlayerInfo playerInfo;
		auto playerItem = *iter;
		playerItem->getPlayerInfoMsg(&playerInfo);
		msg.players.push_back(playerInfo);
	}
	msg.isSuccess = true;
	msg.roomId = m_roomId;
	this->generateRoomStatusMsg(&msg.roomState);
	player->sendMessage(1, msg);
}
void BaseRoom::procPlayerLeave(BasePlayer* player) {
	auto iter = m_setPlayers.find(player);

	if (iter == m_setPlayers.end()) {
		return;
	}
	m_setPlayers.erase(iter);
	this->onPlayerLeave(player);
	player->m_room = NULL;
}

void BaseRoom::procPlayerCreateFriend(BasePlayer* player) {
	BaseDesk* desk = getEmptyDesk();
	BaseMsgS2CCreateFriendDesk ret;
	
	if (!desk) {
		ret.success = false;
		player->sendMessage(2, ret);
	}
	else {
		desk->m_isFriend = true;
		desk->m_deskCode = generateDeskCode();
		ret.success = true;
		ret.deskCode = desk->m_deskCode;
		ret.deskId = desk->m_id;

		m_mapFriendDesks[desk->m_deskCode] = desk;

		player->sendMessage(2, ret);
		this->assignDesk(desk, 0, player);
	}
}

void BaseRoom::procPlayerJoinFriend(BasePlayer* player, const std::string& deskCode) {
	auto iter = m_mapFriendDesks.find(deskCode);
	BaseMsgS2CJoinDesk resp;
	if (iter == m_mapFriendDesks.end()) {
		resp.success = false;
		player->sendMessage(2, resp);
		return;
	}

	auto desk = iter->second;
	desk->m_isFriend = true;
	int chairId = desk->getEmptyChairId();

	if (chairId < 0) {
		resp.success = false;
		player->sendMessage(2, resp);
		return;
	}

	this->assignDesk(desk, chairId, player);
}

void BaseRoom::onPlayerRequestJoinDesk(BasePlayer* player, int deskId, int chairId) {
	if (deskId < 0) {
		deskId = 0;
	}

	if (deskId >= (int)m_vecDesks.size()) {
		BaseMsgS2CJoinDesk msg;
		msg.success = false;
		player->sendMessage(2, msg);
		return;
	}

	if (m_vecDesks[deskId]->m_isFriend) {
		BaseMsgS2CJoinDesk msg;
		msg.success = false; // todo:add error code
		player->sendMessage(2, msg);
		return;
	}

	if (!assignDesk(m_vecDesks[deskId], chairId, player)) {
		BaseMsgS2CJoinDesk msg;
		msg.success = false; // todo:add error code
		player->sendMessage(2, msg);
	}
}

BaseDesk* BaseRoom::getEmptyDesk() {
	for (size_t i = 0; i < m_vecDesks.size(); i++) {
		if (!m_vecDesks[i]->hasPlayerSitted()) {
			return m_vecDesks[i];
		}
	}
	return NULL;
}
string BaseRoom::generateDeskCode() {
	for (;;) {
		int code = rand() % 1000000;
		char strCode[10] = {};
		sprintf(strCode, "%06d", code);

		if (m_mapFriendDesks.find(strCode) == m_mapFriendDesks.end()) {
			return strCode;
		}
	}
}
